﻿namespace Regent
import System # Standard Types
import Boo.Lang.Useful.Attributes # AutoFlags

# The common type that plugs object components into the framework.
# A component can be acquired, restored, updated and released.

# Usage:
# c.Init()
# c.Update()
# c.Release()
class Component:

	# The phase flags.
	[AutoFlags]
	private enum Phase:
		None = 0	# The empty flag.
		Acquire		# The acquire phase manages resources.
		Restore		# The restore phase sets the initial condition of the object.
		Update		# The update phase gives the object life.
		Release		# The release phase manages resources.

	# The current phase flags.
	[property(EnabledPhases)]
	_enabledPhases = 0

	# The acquire phase callback.
	[property(DoAcquirePhase)]
	_acquire as callable

	# The restore phase callback.
	[property(DoRestorePhase)]
	_restore as callable

	# The update phase callback.
	[property(DoUpdatePhase)]
	_update as callable

	# The release phase callback.
	[property(DoReleasePhase)]
	_release as callable

	# The default constructor.
	def constructor():
		SetAcquireEnabled(true)
		SetRestoreEnabled(true)
		SetUpdateEnabled(true)
		SetReleaseEnabled(false)

	# Acquire the resources used by this object.
	def Acquire():
		DoAcquirePhase()

	# Release the resources used by this object.
	def Release():
		DoReleasePhase()

	# Restore the object to a good initial condition.
	def Restore():
		DoRestorePhase()

	# Update the state of this object.
	def Update():
		DoUpdatePhase()

	# Acquire the object resources and restore the object to a good initial condition.
	def Init():
		Acquire()
		Restore()

	# Determines if the update phase will be executed.
	def SetUpdateEnabled(bEnabled):
		SetPhaseEnabled(Phase.Update, bEnabled)

	# Indicates if the update phase will be executed.
	def IsUpdateEnabled():
		return IsPhaseEnabled(Phase.Update)

	# Determines if the acquire phase will be executed.
	def SetAcquireEnabled(bEnabled):
		SetPhaseEnabled(Phase.Acquire, bEnabled)

	# Indicates if the update phase will be executed.
	def IsAcquireEnabled():
		return IsPhaseEnabled(Phase.Acquire)

	# Determines if the restore phase will be executed.
	def SetRestoreEnabled(bEnabled):
		SetPhaseEnabled(Phase.Restore, bEnabled)

	# Indicates if the update phase will be executed.
	def IsRestoreEnabled():
		return IsPhaseEnabled(Phase.Restore)

	# Determines if the release phase will be executed.
	def SetReleaseEnabled(bEnabled):
		SetPhaseEnabled(Phase.Release, bEnabled)

	# Indicates if the update phase will be executed.
	def IsReleaseEnabled():
		return IsPhaseEnabled(Phase.Release)

	# Enables or disables the object phase.
	private def SetPhaseEnabled(ePhase as Phase, bEnabled):
		if bEnabled:
			EnabledPhases = EnabledPhases | cast(int, ePhase)
		else:
			EnabledPhases = EnabledPhases & ~cast(int, ePhase)
		ApplyPhaseCallback(ePhase)

	# Indicates if a certain phase is enabled or disabled.
	private def IsPhaseEnabled(ePhase as Phase):
		return EnabledPhases & cast(int, ePhase) == cast(int, ePhase)

	# Update the callback function for a certain phase.
	private def ApplyPhaseCallback(ePhase as Phase):
		if (ePhase == Phase.Acquire):
			if IsPhaseEnabled(ePhase):
				DoAcquirePhase = DoAcquireStep
			else:
				DoAcquirePhase = DoNothing
		elif (ePhase == Phase.Restore):
			if IsPhaseEnabled(ePhase):
				DoRestorePhase = DoRestoreStep
			else:
				DoRestorePhase = DoNothing
		elif (ePhase == Phase.Update):
			if IsPhaseEnabled(ePhase):
				DoUpdatePhase = DoUpdateStep
			else:
				DoUpdatePhase = DoNothing
		elif (ePhase == Phase.Release):
			if IsPhaseEnabled(ePhase):
				DoReleasePhase = DoReleaseStep
			else:
				DoReleasePhase = DoNothing

	# The acquire phase function.
	private def DoAcquireStep():
		SetAcquireEnabled(false)
		SetReleaseEnabled(true)
		SetRestoreEnabled(true)
		SetUpdateEnabled(true)
		DoAcquire()

	# The restore phase function.
	private def DoRestoreStep():
		DoRestore()

	# The update phase function.
	private def DoUpdateStep():
		DoUpdate()

	# The release phase function.
	private def DoReleaseStep():
		SetReleaseEnabled(false)
		SetAcquireEnabled(true)
		SetRestoreEnabled(false)
		SetUpdateEnabled(false)
		DoRelease()

	# The function that does nothing.
	private def DoNothing():
		pass

	# A client-provided acquire function.
	private virtual def DoAcquire():
		OnAcquire()

	# A client-provided acquire function.
	protected virtual def OnAcquire():
		pass

	# A client-provided restore function.
	private virtual def DoRestore():
		OnRestore()

	# A client-provided restore function.
	protected virtual def OnRestore():
		pass

	# A client-provided update function.
	private virtual def DoUpdate():
		OnUpdate()

	# A client-provided update function.
	protected virtual def OnUpdate():
		pass

	# A client-provided release function.
	private virtual def DoRelease():
		OnRelease()

	# A client-provided release function.
	protected virtual def OnRelease():
		pass
